home *** CD-ROM | disk | FTP | other *** search
/ MacHack 2000 / MacHack 2000.toast / pc / The Hacks / DockStrip / DockStrip.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-24  |  9.4 KB  |  407 lines

  1. #include <LowMem.h>
  2. #include <TextUtils.h>
  3. #include <Gestalt.h> 
  4. #include <MacTypes.h>
  5. #include <Resources.h>
  6. #include <Traps.h>
  7. #include <MixedMode.h>
  8. #include <Processes.h>
  9. #include <QDOffscreen.h>
  10. #include <Folders.h>
  11. #include <CodeFragments.h>
  12.  
  13. #include "DockStrip.h"
  14. #include "MoreCFMPatches.h"
  15.  
  16. InitGrafUPP                gSaveInitGraf;
  17. Get1IndResourceUPP        gSaveGet1IndResource;
  18. SInt16                    gCSAppResFile;
  19.  
  20. Handle            gSdevStub;
  21. Handle            gSdevFragStub;
  22. FSSpec            gInitFileSpec;
  23.  
  24. SDockStripGlobals    gGlobals;
  25.  
  26. pascal void Patched_InitGraf (
  27.     void*        ioGlobals);
  28. pascal void Patched_SetPort (
  29.     GrafPtr        inWindow);
  30. pascal Handle Patched_Get1IndResource (
  31.     ResType        type,
  32.     short        index);
  33. pascal OSErr Patched_GetDiskFragment (
  34.     const FSSpec*        fileSpec,
  35.     long                offset,
  36.     long                length,
  37.     Str63                fragName,
  38.     CFragLoadOptions    findFlags,
  39.     CFragConnectionID*    connID,
  40.     Ptr*                mainAddress,
  41.     Str255                errName);
  42.  
  43.  
  44.  
  45. UniversalProcPtr ApplyTrapPatch (
  46.     UInt16 trap, UniversalProcPtr patchPtr);
  47. Boolean HaveProcessManager();
  48. GWorldPtr CreateGWorld (void);
  49. Handle LoadSdevStub (void);
  50. Handle LoadSdevFragStub (void);
  51. Handle PrepareSdevStub (
  52.     short    inIndex);
  53. ProcPtr PrepareSdevFragStub (
  54.     ProcPtr    inRealRoutine);
  55. void RememberStub (
  56.     Handle stub,
  57.     Handle module);
  58. void RememberFragStub (
  59.     ProcPtr stub,
  60.     ProcPtr module);
  61.  
  62. void main (void) {
  63.     Handle        initCode = nil;
  64.     THz            theZone;
  65.     SInt16        myResFile;
  66.     OSErr        err;
  67.     SInt16        systemVolume;
  68.     Str31        myPath;
  69.     SInt32        myDirID;
  70.  
  71.     /* Find reference number for the extension file */
  72.     myResFile = CurResFile ();
  73.     err = ResError ();
  74.     
  75.     if (err == noErr) {
  76.         /* Find startup disk volume reference number */
  77.         long    systemFolder;
  78.         err = FindFolder (kOnSystemDisk, kSystemFolderType, kDontCreateFolder, &systemVolume, &systemFolder);
  79.     }
  80.  
  81.     if (err == noErr) {
  82.         /* Figure out which file we're in */
  83.         FCBPBRec    paramBlock = {
  84.             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
  85.     
  86.         paramBlock.ioNamePtr = myPath;
  87.         paramBlock.ioVRefNum = systemVolume;
  88.         paramBlock.ioRefNum = myResFile;
  89.  
  90.         err = PBGetFCBInfoSync (¶mBlock);
  91.         myDirID = paramBlock.ioFCBParID;
  92.     }
  93.     
  94.     if (err == noErr) {
  95.         err = FSMakeFSSpec (systemVolume, myDirID, myPath, &gInitFileSpec);
  96.     }
  97.     
  98.     /* Detach and lock the code resource */
  99.     initCode = Get1Resource ('INIT', 0);
  100.     if (initCode == nil)
  101.         goto failure;
  102.  
  103.     DetachResource (initCode);
  104.     if (ResError () != noErr) 
  105.         goto failure;
  106.     
  107.     theZone = GetZone();
  108.     SetZone (SystemZone());
  109.  
  110.     HLockHi (initCode);
  111.     
  112.     /* Install the InitGrafPatch */
  113.     gSaveInitGraf = (InitGrafUPP) ApplyTrapPatch (_InitGraf, NewInitGrafProc (Patched_InitGraf));
  114.  
  115. failure:;
  116. }
  117.     
  118. UniversalProcPtr ApplyTrapPatch (
  119.     UInt16 trap, UniversalProcPtr patchPtr) {
  120.  
  121.     UniversalProcPtr trapPtr;
  122.     
  123.     if (patchPtr == nil)
  124.         return nil;
  125.  
  126.     trapPtr = NGetTrapAddress (trap, (trap & 0x0800) ? ToolTrap : OSTrap);
  127.     NSetTrapAddress (patchPtr, trap, (trap & 0x0800) ? ToolTrap : OSTrap);
  128.     return trapPtr;
  129. }
  130.  
  131. pascal void Patched_InitGraf (
  132.     void*        ioGlobals) {
  133.     
  134.     ProcessSerialNumber        currentProcess = { 0, kCurrentProcess };
  135.     ProcessInfoRec            processInfo;
  136.     OSErr err;
  137.     
  138.     processInfo.processInfoLength = sizeof (processInfo);
  139.     processInfo.processAppSpec = nil;
  140.     processInfo.processName = nil;
  141.     
  142.     if (HaveProcessManager ()) {
  143.         err = GetProcessInformation (¤tProcess, &processInfo);
  144.     
  145.         if ((err == noErr) && (processInfo.processSignature == 'sdev')) {
  146.             static Boolean beenHere = false;
  147.             if (!beenHere) {
  148.                 GrafPtr savePort;
  149.                 gSaveGet1IndResource = ApplyTrapPatch (_Get1IxResource, NewGet1IndResourceProc (Patched_Get1IndResource));
  150.                 MorePatchTVector ((TVector*)GetDiskFragment, (TVector*)Patched_GetDiskFragment, dockStripSignature, nil);
  151.                 gGlobals.offscreenGWorld = CreateGWorld ();
  152.                 gGlobals.updatePort = CreateGWorld ();
  153.                 OpenCPort (&gGlobals.ourPort);
  154.                 gSdevStub = LoadSdevStub ();
  155.                 gSdevFragStub = LoadSdevFragStub ();
  156.                 gCSAppResFile = CurResFile ();
  157.                 gGlobals.saveSetPort = ApplyTrapPatch (_SetPort, NewSetPortProc (Patched_SetPort));
  158.                 NewGestaltValue (dockStripGestalt, (SInt32)&gGlobals);
  159.                 beenHere = true;
  160.             }
  161.         }
  162.     }
  163.     
  164.     CallInitGrafProc (gSaveInitGraf, ioGlobals);
  165. }
  166.  
  167. pascal void Patched_SetPort (
  168.     GrafPtr        inGrafPort) {
  169.     
  170.     CallSetPortProc (gGlobals.saveSetPort, inGrafPort);
  171. //    CallSetPortProc (gGlobals.saveSetPort, gGlobals.offscreenGWorld);
  172. //    CallSetPortProc (gGlobals.saveSetPort, gGlobals.ourPort);
  173. }
  174.  
  175. pascal Handle Patched_Get1IndResource (
  176.     ResType        inResType,
  177.     short        inIndex)
  178. {
  179. //    DebugStr ("\pGet1IndResource patch");
  180.     if ((inResType == 'sdev') && (CurResFile () != gCSAppResFile))
  181.         return PrepareSdevStub (inIndex);
  182.  
  183.     return CallGet1IndResourceProc (gSaveGet1IndResource, inResType, inIndex);
  184. }
  185.  
  186. Boolean HaveProcessManager()
  187. {
  188.     static    Boolean    alreadyKnowWeHaveIt = false;
  189.     SInt32            response;
  190.     OSErr            error;
  191.     
  192.     if (alreadyKnowWeHaveIt)
  193.         return true;
  194.  
  195.     error = Gestalt (gestaltOSAttr, &response);
  196.     
  197.     if ((error != noErr) || ((response & gestaltLaunchControl) == 0)) {
  198.         return false;
  199.     }
  200.     
  201.     alreadyKnowWeHaveIt = true;
  202.     
  203.     return true;
  204. }
  205.  
  206. GWorldPtr CreateGWorld (void)
  207. {
  208.     GWorldPtr    offscreenGWorld;
  209.     OSErr        err;
  210.     Rect        bounds = {0, 0, 768, 1024};
  211.     GrafPtr        savePort;
  212.     RGBColor    back = {0xC000, 0xC000, 0xC000};
  213.     RGBColor    old;
  214.  
  215.     /* Create the offscreen GWorld */
  216.     err = NewGWorld (&offscreenGWorld, 0, &bounds, nil, nil, useTempMem);
  217.     if (err != noErr) {
  218.         DebugStr ("\pNewGWorld failed");
  219.         return nil;
  220.     }
  221.  
  222.     GetPort (&savePort);
  223.     SetPort ((GrafPtr)offscreenGWorld);
  224.     GetBackColor (&old);
  225.     RGBBackColor (&back);
  226.     EraseRect (&bounds);
  227.     RGBBackColor (&old);
  228.     SetPort (savePort);
  229.     
  230.     return offscreenGWorld;
  231. }
  232.  
  233. Handle LoadSdevStub (void)
  234. {
  235.     Handle sdevStub;
  236.     
  237.     SInt16 resFile = FSpOpenResFile (&gInitFileSpec, fsRdWrPerm);
  238.     if (resFile == kResFileNotOpened) {
  239.         DebugStr ("\pResource file not found?");
  240.         return nil;
  241.     }
  242.  
  243.     sdevStub = Get1Resource ('sdev', 128);
  244.     if (sdevStub == nil) {
  245.         DebugStr ("\pSdev stub not found?");
  246.         return nil;
  247.     }
  248.     
  249.     DetachResource (sdevStub);
  250.     CloseResFile (resFile);
  251.     return sdevStub;
  252. }
  253.  
  254. Handle LoadSdevFragStub (void)
  255. {
  256.     Handle sdevStub;
  257.     
  258.     SInt16 resFile = FSpOpenResFile (&gInitFileSpec, fsRdWrPerm);
  259.     if (resFile == kResFileNotOpened) {
  260.         DebugStr ("\pResource file not found?");
  261.         return nil;
  262.     }
  263.  
  264.     sdevStub = Get1Resource ('sdev', 129);
  265.     if (sdevStub == nil) {
  266.         DebugStr ("\pSdev frag stub not found?");
  267.         return nil;
  268.     }
  269.     
  270.     DetachResource (sdevStub);
  271.     CloseResFile (resFile);
  272.     return sdevStub;
  273. }
  274.  
  275. Handle PrepareSdevStub (
  276.     short    inIndex)
  277. {
  278.     Handle    newSdevStub;
  279.     OSErr    err;
  280.     UInt32    index;
  281.     Handle    realResource;
  282.     
  283. //    DebugStr ("\pPrepareSdevStub");
  284.  
  285.     SetResLoad (true);
  286.     realResource = CallGet1IndResourceProc (gSaveGet1IndResource, 'sdev', inIndex);
  287.  
  288.     if (realResource == nil)
  289.         return nil;
  290.  
  291.     DetachResource (realResource);    
  292.     HLock (realResource);
  293.         
  294.     newSdevStub = gSdevStub;
  295.     err = HandToHand (&newSdevStub);
  296.     if (err != noErr) {
  297.         DebugStr ("\pOut of memory in PrepareSdevStub?");
  298.         return nil;
  299.     }
  300.     
  301.     HLock (newSdevStub);
  302.     
  303.     /* Slam the pointer into the new stub */
  304.     for (index = 0; index < GetHandleSize (newSdevStub); index += 1) {
  305.         if (*(UInt32*)((*newSdevStub) + index) == 0xDEADBEEFL) {
  306.             BlockMove (&realResource, &((*newSdevStub) [index]), sizeof (UInt32));
  307.             break;
  308.         }
  309.     }
  310.     RememberStub (newSdevStub, realResource);
  311.     return newSdevStub;
  312. }
  313.  
  314. ProcPtr PrepareSdevFragStub (
  315.     ProcPtr        realMainAddress)
  316. {
  317.     Handle    newSdevStub;
  318.     OSErr    err;
  319.     ProcPtr    ourAddress;
  320.     CFragConnectionID    connectionID;
  321.     Str255    errName;
  322.     
  323. //    DebugStr ("\pPrepareSdevStub");
  324.  
  325.     newSdevStub = gSdevFragStub;
  326.     err = HandToHand (&newSdevStub);
  327.     if (err != noErr) {
  328.         DebugStr ("\pOut of memory in PrepareSdevFragStub?");
  329.         return nil;
  330.     }
  331.     
  332.     HLock (newSdevStub);
  333.     
  334.     err = GetMemFragment (*newSdevStub, GetHandleSize (newSdevStub), "\pSdev stub", kPrivateCFragCopy,
  335.         &connectionID, (Ptr*)&ourAddress, errName);
  336.     if (err != noErr) {
  337.         DebugStr ("\pError in GetMemFragment");
  338.         return nil;
  339.     }
  340.  
  341.     RememberFragStub (ourAddress, realMainAddress);
  342.  
  343.     // Initialize the stub
  344.     ((SdevMainProcPtr)ourAddress) ((UInt32)realMainAddress, 0, 0, 0);
  345.     return ourAddress;
  346. }
  347.  
  348. void RememberStub (
  349.     Handle stub,
  350.     Handle module)
  351. {
  352.     UInt32 index;
  353.     for (index = 0; index < sizeof (gGlobals.moduleList) / sizeof (SStubInfo); index++) {
  354.         if (gGlobals.moduleList [index].stub.handle == nil) {
  355.             gGlobals.moduleList [index].stub.handle = stub;
  356.             gGlobals.moduleList [index].module.handle = module;
  357.             gGlobals.moduleList [index].goingUp = false;
  358.             gGlobals.moduleList [index].startingUp = false;
  359.             gGlobals.moduleList [index].amountWider = 0;
  360.             return;
  361.         }
  362.     }
  363.     
  364.     DebugStr ("\pStub list too small");
  365. }
  366.  
  367. void RememberFragStub (
  368.     ProcPtr stub,
  369.     ProcPtr module)
  370. {
  371.     UInt32 index;
  372.     for (index = 0; index < sizeof (gGlobals.moduleList) / sizeof (SStubInfo); index++) {
  373.         if (gGlobals.moduleList [index].stub.procPtr == nil) {
  374.             gGlobals.moduleList [index].stub.procPtr = stub;
  375.             gGlobals.moduleList [index].module.procPtr = module;
  376.             gGlobals.moduleList [index].goingUp = false;
  377.             gGlobals.moduleList [index].startingUp = false;
  378.             gGlobals.moduleList [index].amountWider = 0;
  379.             return;
  380.         }
  381.     }
  382.     
  383.     DebugStr ("\pStub list too small");
  384. }
  385.  
  386. pascal OSErr Patched_GetDiskFragment (
  387.     const FSSpec*        fileSpec,
  388.     long                offset,
  389.     long                length,
  390.     Str63                fragName,
  391.     CFragLoadOptions    findFlags,
  392.     CFragConnectionID*    connID,
  393.     Ptr*                mainAddress,
  394.     Str255                errName)
  395. {
  396.     OSErr result;
  397. //    DebugStr ("\pPatched GetDiskFragment");
  398.     
  399.     result = ((Patched_GetDiskFragmentProcPtr) gMoreCFMPatchesCallThrough)(fileSpec, offset, length, fragName, findFlags,
  400.         connID, mainAddress, errName);
  401.         
  402.     if ((result == noErr) && (*(UInt32*)(&(LMGetCurApName ()[1])) == 'Cont')) {
  403.         *mainAddress = (Ptr)PrepareSdevFragStub ((ProcPtr)*mainAddress);
  404.     }
  405.     
  406.     return result;
  407. }